package utils

import (
	"fmt"
	"strings"
	"sync"
)

/*
循环写入字符串列表
*/
type RingStrlist struct {
	lk       sync.RWMutex
	writeidx int // 下一个写的位置
	slot_n   int
	lst      []string
}

func NewRingStrlist(slot_n int) *RingStrlist {
	rval := &RingStrlist{slot_n: slot_n, lst: make([]string, slot_n)}
	return rval
}

func (this *RingStrlist) SlotN() int {
	return this.slot_n
}

/*
请空所有数据
*/
func (this *RingStrlist) Reset() {
	this.lk.Lock()
	defer this.lk.Unlock()
	for i := 0; i < len(this.lst); i++ {
		this.lst[i] = ""
	}
}

func (this *RingStrlist) Join(sep string) string {
	this.lk.RLock()
	defer this.lk.RUnlock()
	idx := this.writeidx
	if idx == 0 {
		return strings.Join(this.lst, sep)
	}
	prefix := strings.Join(this.lst[this.writeidx:], sep)
	suffix := strings.Join(this.lst[:this.writeidx], sep)
	return fmt.Sprintf("%s%s%s", prefix, sep, suffix)
}

func (this *RingStrlist) incWriteIdx() {
	this.writeidx++
	if this.writeidx >= len(this.lst) {
		this.writeidx = 0
	}
}

func (this *RingStrlist) GetLastWriteIdx() int {
	this.lk.RLock()
	defer this.lk.RUnlock()
	return this.innerGetLastWriteIdx()
}

func (this *RingStrlist) innerGetLastWriteIdx() int {
	if this.writeidx == 0 {
		return len(this.lst) - 1
	}
	return this.writeidx - 1
}

/*
如果没有则写入，存在则更新
*/
func (this *RingStrlist) CheckWrite(v string) {
	this.lk.Lock()
	defer this.lk.Unlock()
	idx := this.innerIndex(v)
	if idx == -1 {
		this.innerWriteVal(v)
	} else {
		this.innerMove2Last(v)
	}
}

func (this *RingStrlist) innerWriteVal(v string) {
	this.lst[this.writeidx] = v
	this.incWriteIdx()
}

func (this *RingStrlist) WriteVal(v string) {
	this.lk.Lock()
	defer this.lk.Unlock()
	this.innerWriteVal(v)
}

/*
*
最后写入下标索引， 最后一个的索引为:0

	0，1，2，3，4，5，6,7, 8, 9

1:      f  w
2:   w  f
*/
func (this *RingStrlist) IndexLastWrite(v string) int {
	this.lk.RLock()
	defer this.lk.RUnlock()
	f := this.innerIndex(v)
	if f == -1 {
		return f
	}
	w := this.innerGetLastWriteIdx()
	if f <= w {
		return w - f
	} else {
		return this.slot_n - (f - w)
	}
}

func (this *RingStrlist) Index(v string) int {
	this.lk.RLock()
	defer this.lk.RUnlock()
	for i := 0; i < len(this.lst); i++ {
		if this.lst[i] == v {
			return i
		}
	}
	return -1
}

func (this *RingStrlist) innerIndex(v string) int {
	for i := 0; i < len(this.lst); i++ {
		if this.lst[i] == v {
			return i
		}
	}
	return -1
}

func (this *RingStrlist) MoveWriteIdx(w int) {
	this.lk.Lock()
	defer this.lk.Unlock()
	this.writeidx = w % this.slot_n
}

/*
*

	移除一个元素
*/
func (this *RingStrlist) Remove(v string) bool {
	this.lk.Lock()
	defer this.lk.Unlock()
	f := this.innerIndex(v)
	if f == -1 {
		return false
	}

	if f == this.writeidx { // 下一个就是
		this.lst[f] = "" // 直接去掉
	} else {
		w := this.innerGetLastWriteIdx()
		if w == f { // 最后一个
			this.lst[f] = ""
			this.writeidx = w
		} else if f < this.writeidx { // f > 0 && f < this.writeidx
			// 0, 1, 2, 3, 4, 5, 6, 7
			//    f     w
			copy(this.lst[f:this.writeidx], this.lst[f+1:this.writeidx])
			this.writeidx--
			this.lst[this.writeidx] = ""
		} else { // f > writeidx
			// 0, 1, 2, 3, 4, 5, 6, 7
			//             w     f
			copy(this.lst[this.writeidx+1:f+1], this.lst[this.writeidx:f+1])
			this.lst[this.writeidx] = ""
		}
	}

	return true
}

func (this *RingStrlist) Move2Last(v string) bool {
	this.lk.Lock()
	defer this.lk.Unlock()
	return this.innerMove2Last(v)
}

/*
将元素移动到最后一个插入的地方
*/
func (this *RingStrlist) innerMove2Last(v string) bool {
	idx := this.innerIndex(v)
	if idx == -1 {
		return false
	}

	if idx == this.writeidx { // 下一个就是
		this.incWriteIdx()
	} else {
		lastwriteidx := this.innerGetLastWriteIdx()
		if lastwriteidx == idx { // 最后一个就是
			return true
		} else if idx < this.writeidx {
			// 0, 1, 2, 3, 4, 5, 6, 7
			//    f     w
			copy(this.lst[idx:this.writeidx], this.lst[idx+1:this.writeidx])
			this.lst[lastwriteidx] = v
		} else {
			// 0, 1, 2, 3, 4, 5, 6, 7
			//             w     f
			copy(this.lst[this.writeidx+1:idx+1], this.lst[this.writeidx:idx+1])
			this.lst[this.writeidx] = v
			this.incWriteIdx()
		}
	}
	return true
}
